#!/usr/bin/env python

##  flamingo - 2D Game Engine
##  Copyright (C) 2009 Bradley Zeis
##
##  This program is free software: you can redistribute it and/or modify
##  it under the terms of the GNU General Public License as published by
##  the Free Software Foundation, either version 3 of the License, or
##  (at your option) any later version.
##
##  This program is distributed in the hope that it will be useful,
##  but WITHOUT ANY WARRANTY; without even the implied warranty of
##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##  GNU General Public License for more details.
##
##  You should have received a copy of the GNU General Public License
##  along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##  Bradley Zeis
##  flamingoengine@gmail.com

"""Unit Tests for flamingo.flmath"""

import unittest
import flamingo
import math
import pickle
from numbers import Number

class TestPow(unittest.TestCase):
    def setUp(self):
        self.data = [2, 3, 4, 7, 17, 710, 483, 60495, 712345]
        self.bad = ["hello world!", [1, 2, 3], {'foo': 'bar'},
                    flamingo.flmath.Vector([1, 1])]

    def testClosestIsNumber(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.closest_pow2(d), Number))

    def testClosestIsPow2(self):
        for d in self.data:
            result = flamingo.flmath.closest_pow2(d)
            self.assertEqual(math.log(result, 2) % 1, 0.0)

    def testClosestIsOne(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.closest_pow2(d) >= 1)

    def testClosestIsClosest(self):
        for d in self.data:
            less = math.pow(2, math.ceil(math.log(d)/math.log(2.0)))
            greater = math.pow(2, math.floor(math.log(d)/math.log(2.0)))
            lessd = d - less
            greaterd = greater - d

            if lessd < greaterd:
                self.assertEqual(flamingo.flmath.closest_pow2(d), greater)
            else:
                self.assertEqual(flamingo.flmath.closest_pow2(d), less)

    def testClosestBad(self):
        for b in self.bad:
            self.assertRaises(TypeError,
                              flamingo.flmath.closest_pow2, b)

    def testClosestNeg(self):
        for d in self.data:
            self.assertRaises(ValueError, flamingo.flmath.closest_pow2, -d)

    def testNextIsNumber(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.next_pow2(d), Number))

    def testNextIsPow2(self):
        for d in self.data:
            result = flamingo.flmath.next_pow2(d)
            self.assertEqual(math.log(result, 2) % 1, 0.0)

    def testNextIsOne(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.next_pow2(d) >= 1)

    def testNextGreater(self):
        for d in self.data:
            result = flamingo.flmath.next_pow2(d)
            self.assertTrue(result >= d)

    def testNextBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.next_pow2, b)

    def testNextNeg(self):
        for d in self.data:
            self.assertRaises(ValueError, flamingo.flmath.next_pow2, -d)

    def testPrevIsNumber(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.prev_pow2(d), Number))

    def testPrevIsPow2(self):
        for d in self.data:
            result = flamingo.flmath.prev_pow2(d)
            self.assertEqual(math.log(result, 2) % 1, 0.0)

    def testPrevIsOne(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.prev_pow2(d) >= 1)

    def testPrevLess(self):
        for d in self.data:
            result = flamingo.flmath.prev_pow2(d)
            if result is None:
                self.assertTrue(False)
            self.assertTrue(result <= d)

    def testPrevBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.prev_pow2, b)

    def testPrevNeg(self):
        for d in self.data:
            self.assertRaises(ValueError, flamingo.flmath.prev_pow2, -d)


class TestDistance(unittest.TestCase):
    def setUp(self):
        ## data = [[point, point, distance, distance_sq]]
        self.data = [[(0, 0), (0, 1), 1, 1],
                     [(2.5, 2),(4.76, 3.1), 2.5134, 6.3176],
                     [(10, 16),(100, 160), 169.8116, 28836],
                     [flamingo.flmath.Vector([1.2, 1]), flamingo.flmath.Vector([16, 1]), 14.8, 219.04],
                     [(0, 0), (0, 0), 0, 0],
                     [flamingo.flmath.Vector([0, 0]), flamingo.flmath.Vector([0, 0]), 0, 0]]

        self.long = [[(21, 4, 6, 4, 3), (14, 16, 71, 723, 5)],
                     [(10, 9, 8, 7, 6, 5, 4, 3, 2, 1), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)],
                     [(1, 2, 3, 4), (5, 4, 3, 2, 1)]]

        self.short = [[(), ()]]

        self.bad = [["hello", "world"],
                    [{'foo': 'bar'}, {'bar': 'foo'}],
                    ["hello world", 35]]

    def testIsNumber(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.distance(d[0], d[1]), Number))

    def testIsPos(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.distance(d[0], d[1]) >= 0)

    def testValue(self):
        for d in self.data:
            result = flamingo.flmath.distance(d[0], d[1])
            self.assertEqual(round(result, 2), round(d[2], 2))

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.distance, b[0],b[1])

    ##-------- Sq
    def testIsNumberSq(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.distance_sq(d[0], d[1]), Number))

    def testIsPosSq(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.distance_sq(d[0], d[1]) >= 0)

    def testValueSq(self):
        for d in self.data:
            result = flamingo.flmath.distance_sq(d[0], d[1])
            self.assertEqual(round(result, 2), round(d[3], 2))

    def testBadSq(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.distance_sq, b[0],b[1])


class TestMidpoint(unittest.TestCase):
    def setUp(self):
        ## data = [[point, point, midpoint]]
        self.data = [[(0, 0), (0, 1), (0, 0.5)],
                     [(2.5, 2),(4.76, 3.1), (3.63, 2.55)],
                     [(10, 16),(100, 160), (55, 88)],
                     [flamingo.flmath.Vector([1.13, 1]), (16, 1), (8.565, 1)],
                     [(0, 0), (0, 0), (0, 0)]]

        self.wrong = [[(), ()],
                      [(2,), (1,)]]

        self.bad = [["hello", "world"],
                    [{'foo': 'bar'}, {'bar': 'foo'}],
                    ["hello world", 35]]

    def testValue(self):
        for d in self.data:
            result = flamingo.flmath.midpoint(d[0], d[1])
            self.assertEqual(round(result[0]), round(d[2][0]))
            self.assertEqual(round(result[1]), round(d[2][1]))

    def testWrong(self):
        for d in self.wrong:
            self.assertRaises(TypeError, flamingo.flmath.midpoint, d[0], d[1])

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.midpoint, b[0],b[1])


class TestArea(unittest.TestCase):
    def setUp(self):
        ## [[data], area, signed_area]
        self.data = [[ [(1, 1), (-1, 1), (-1, -1), (1, -1)], 4, 4],
                     [ [(1, 1), (1, -1), (-1, -1), (-1, 1)], 4, -4],
                     [ [(0, 15.4), (-64.24, -10.1), (14.4, -10.1)], 1002.66, 1002.66 ],
                     [ [(0, 15.4), (14.4, -10.1), (-64.24, -10.1)], 1002.66, -1002.66 ]]

        self.odata = [[ [(1, 1), (-1, 1), (-1, -1), (1, -1)], True],
                      [ [(1, 1), (1, -1), (-1, -1), (-1, 1)], False],
                      [ [(0, 15.4), (-64.24, -10.1), (14.4, -10.1)], True],
                      [ [(0, 15.4), (14.4, -10.1), (-64.24, -10.1)], False]]

        self.bad = [["meow", "rawrf", "ROAR"],
                    [("meow", "woof"), ("woof", "meow"), ("rawr", "roar")],
                    [{'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}],
                    [(1,), (2,), (3,)],
                    [(1, 2), (3, 4)],
                    [(1, 2)],
                    []]

    ##-------- Pos Area
    def testIsNumber(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.area(d[0]), Number))

    def testIsPos(self):
        for d in self.data:
            self.assertTrue(flamingo.flmath.area(d[0]) > 0)

    def testValue(self):
        for d in self.data:
            result = flamingo.flmath.area(d[0])
            self.assertEqual(round(result, 2), round(d[1], 2))

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.area, b)

    ##-------- Signed Area
    def testIsNumberS(self):
        for d in self.data:
            self.assertTrue(isinstance(flamingo.flmath.signed_area(d[0]), Number))

    def testValueS(self):
        for d in self.data:
            result = flamingo.flmath.signed_area(d[0])
            self.assertEqual(round(result, 2), round(d[2], 2))

    def testBadS(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.signed_area, b)

    ##-------- Orientation
    def testValueO(self):
        for d in self.odata:
            result = flamingo.flmath.orientation_poly(d[0])
            self.assertEqual(result, d[1])

    def testBadO(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.orientation_poly, b)


class TestNormalizeAngle(unittest.TestCase):
    def setUp(self):
        self.datad = [[45, 45],
                      [360, 0],
                      [400, 40],
                      [4000, 40],
                      [-100, 260]]
        self.datar = [[math.radians(45), math.radians(45)],
                      [math.radians(360), math.radians(0)],
                      [math.radians(400), math.radians(40)],
                      [math.radians(4000), math.radians(40)],
                      [math.radians(-100), math.radians(260)]]
        self.bad = ["meow",
                    [16],
                    {'foo': 'bar'}]

    ##-------- Degress
    def testNumber(self):
        for i in range(0, 1000):
            self.assertTrue(isinstance(flamingo.flmath.normalize_angle(i), Number))

    def testIsPos(self):
        for i in range(0, 1000):
            self.assertTrue(flamingo.flmath.normalize_angle(i) >= 0)

    def testValue(self):
        for d in self.datad:
            self.assertEqual(flamingo.flmath.normalize_angle(d[0]), d[1])

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.normalize_angle, b)

    ##-------- Radians
    def testNumberR(self):
        for i in range(0, 1000):
            self.assertTrue(isinstance(flamingo.flmath.normalize_angler(i), Number))

    def testIsPosR(self):
        for i in range(0, 1000):
            self.assertTrue(flamingo.flmath.normalize_angler(i) >= 0)

    def testValueR(self):
        for d in self.datar:
            self.assertAlmostEqual(flamingo.flmath.normalize_angler(d[0]), d[1])

    def testBadR(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.normalize_angler, b)


class TestNormalizePoly(unittest.TestCase):
    def setUp(self):
        self.p = [flamingo.flmath.Vector((-1,1)), (-1,-1), [1,-1], (1,1)]

        self.bad = [[1, 2, 3],
                    [{'foo': 'bar'}, "meow!", (1, 2), ["3","4"]],
                    [(1,), (2,), (3,)]]

    def testNormalize(self):
        self.assertEqual(flamingo.flmath.normalize_poly(self.p), self.p)
        p = [flamingo.flmath.Vector((-1,1)), (-1,-1), [1,-1], (1,1), (-1, 1)]
        self.assertEqual(flamingo.flmath.normalize_poly(p), self.p)
        self.assertEqual(flamingo.flmath.normalize_poly(self.p, 1), p)

        p = [(-1,1), (-1,-1), [1,-1], (1,1), (-1, 1), (-1,-1)]
        self.assertEqual(flamingo.flmath.normalize_poly(p), self.p)
        self.assertEqual(flamingo.flmath.normalize_poly(self.p, 2), p)

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.normalize_poly, b)


class TestPolySimplify(unittest.TestCase):
    def setUp(self):
        self.data = [[(1, 0), (1, 8.12), (19.95, 5), (-1, -5), (-1.25, -5.15)],
                     [[-1, 0], [-1, -4.12], [-16.95, -5], [14, 5], [1.25, 5.15]]]

        self.bad = [["meow", "rawrf", "ROAR"],
                    [("meow", "woof"), ("woof", "meow"), ("rawr", "roar")],
                    [{'foo': 'bar'}, {'foo': 'bar'}, {'foo': 'bar'}]]

    def testReturnsList(self):
        for i in range(8):
            for d in self.data:
                self.assertTrue(isinstance(flamingo.flmath.simplify_poly(d, i), list))

    def testReturnsCoords(self):
        for i in range(8):
            for d in self.data:
                result = flamingo.flmath.simplify_poly(d, i)
                b = True

                for p in result:
                    if not (isinstance(p[0], Number) and isinstance(p[1], Number)):
                        b = b and False
                        break

                self.assertTrue(b)

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.simplify_poly, b, 1)

class TestVector(unittest.TestCase):
    def setUp(self):
        self.v = flamingo.flmath.Vector((111, 222))

        self.bad = [(8, {'foo': 'bar'}),
                    ("meow!", "imah vector!")]

    def testAccess(self):
        v = self.v.copy()
        self.assertEqual(v.x, 111)
        self.assertEqual(v.y, 222)
        v.x = 333
        v[1] = 444
        self.assertEqual(v[0], 333)
        self.assertEqual(v[1], 444)

    def testMath(self):
        v = self.v.copy()
        self.assertEqual(v + 1, flamingo.flmath.Vector((112, 223)))
        self.assertEqual(v - 2, [109,220])
        self.assertEqual(v * 3, (333,666))
        self.assertEqual(v / 2.0, flamingo.flmath.Vector((55.5, 111)))
        self.assertEqual(v / 2, (55.5, 111))
        self.assertEqual(v ** flamingo.flmath.Vector((2,3)), [12321, 10941048])
        self.assertEqual(v + [-11, 78], flamingo.flmath.Vector((100, 300)))

    def testReverseMath(self):
        v = self.v.copy()
        self.assertEqual(1 + v, flamingo.flmath.Vector((112,223)))
        self.assertEqual(2 - v, [-109,-220])
        self.assertEqual(3 * v, (333,666))
        self.assertEqual([111,222] ** flamingo.flmath.Vector((2,3)), [12321, 10941048])
        self.assertEqual(v + flamingo.flmath.Vector((1,1)), [112, 223])

    def testInplaceMath(self):
        inplace_vec = flamingo.flmath.Vector((5, 13))
        inplace_src = flamingo.flmath.Vector((inplace_vec))
        inplace_vec *= .5
        inplace_vec += .5
        inplace_vec /= 3
        inplace_vec += flamingo.flmath.Vector((-1, -1))
        alternate = (inplace_src*.5 + .5)/3 + [-1, -1]
        self.assertEqual(inplace_vec, alternate)

    def testUnary(self):
        v = self.v.copy()
        v = -v
        self.assertEqual(v, [-111,-222])
        v = abs(v)
        self.assertEqual(v, [111,222])

    def testLength(self):
        v = flamingo.flmath.Vector((3, 4))
        self.assertEqual(v.length, 5)
        v.length = 10
        self.assertEqual(v, [6, 8])


    def testAngles(self):
        v = flamingo.flmath.Vector((0,3))
        self.assertEqual(v.angle, 90)
        v.angle = 0
        self.assertEqual(v, (3, 0))
        v2 = (-3,0)
        self.assertEqual(v.angle_about(v2), 0)
        v2 = flamingo.flmath.Vector(v2)
        self.assertEqual(v2.angle_about(v), 180)
        v.angle = 90, (0,0)
        self.assertEqual(v, [0, 3])

    def testComparison(self):
        int_vec = flamingo.flmath.Vector((3, -2))
        flt_vec = flamingo.flmath.Vector((3.0, -2.0))
        zero_vec = flamingo.flmath.Vector((0, 0))
        self.assertEqual(int_vec, flt_vec)
        self.assertNotEqual(int_vec, zero_vec)
        self.assertFalse(flt_vec == zero_vec)
        self.assertFalse(flt_vec != int_vec)
        self.assertEqual(int_vec, (3, -2))
        self.assertNotEqual(int_vec, [0, 0])
        self.assertNotEqual(int_vec, 5)

    def testConversion(self):
        self.assertEqual(list(self.v), [111, 222])
        self.assertTrue(isinstance(list(self.v), list))
        self.assertEqual(tuple(self.v), (111, 222))
        self.assertTrue(isinstance(tuple(self.v), tuple))

    def testPickle(self):
        testvec = flamingo.flmath.Vector((5, .3))
        testvec_str = pickle.dumps(testvec)
        loaded_vec = pickle.loads(testvec_str)
        self.assertEqual(testvec, loaded_vec)

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.Vector, b)


class TestPolygon(unittest.TestCase):
    def setUp(self):
        self.p = flamingo.flmath.Polygon([(-1,1), (-1,-1), (1,-1), (1,1)])

        self.bad = [[{'foo': 'bar'}, "meow!", (1, 2), ["3","4"]]]

    def testAccess(self):
        p = self.p.copy()
        self.assertEqual(p[0], (-1, 1))
        p[0] = (-5, 5)
        self.assertEqual(p[0], (-5, 5))
        self.assertTrue(isinstance(p[0], flamingo.flmath.Vector))
        self.assertEqual(p.center, (-1, 1))
        p[1] = -4, 7
        self.assertEqual(p[1], (-4, 7))
        p[3] = 16
        self.assertEqual(p[3], (16, 16))

    def testComparison(self):
        p = self.p.copy()
        self.assertEqual(p, [(-1,1), (-1,-1), (1,-1), (1,1)])
        q = flamingo.flmath.Polygon([(-1,1), (-1,-1), (1,-1), (1,1)])
        self.assertEqual(p, q)
        q[0] = -5, 5
        self.assertNotEqual(p, q)
        self.assertNotEqual(q, p)

    def testAppend(self):
        p = self.p.copy()
        self.assertRaises(AttributeError, flamingo.flmath.Polygon.append, p, (0, 2.5))

        p.enable(flamingo.constants.POLYGON_MUTABLE_LENGTH)
        p.append((0, 2.5))
        self.assertEqual(len(p), 5)
        self.assertEqual(p.center, (0, 0.5))
        p[4] -= 0, 1
        self.asserEqual(p.center, (0,0))
        p.append((-0.5, 1))
        self.assertEqual(len(p), 6)
        self.asserEqual(p.center, (0,0))

    def testInsert(self):
        p = self.p.copy()
        self.assertRaises(AttributeError, flamingo.flmath.Polygon.insert, p, 1, (-2.5, 0))

        p.enable(flamingo.constants.POLYGON_MUTABLE_LENGTH)
        p.insert(1, (-2.5, 0))
        self.assertEqual(len(p), 5)
        self.assertEqual(p.center, (-0.5, 0))

    def testRemove(self):
        p = self.p.copy()
        self.assertRaises(AttributeError, flamingo.flmath.Polygon.insert, p, 3)

        p.enable(flamingo.constants.POLYGON_MUTABLE_LENGTH)
        p.remove(3)
        self.assertEqual(len(p), 3)
        self.assertEqual(p.center, -1.0/3)
        self.assertRaises(TypeError, Polygon.remove, p, 1)

    def testConversion(self):
        p = self.p.copy()
        self.assertEqual(list(p), p)
        self.assertTrue(isinstance(list(p), list))
        self.assertEqual(tuple(p), p)
        self.assertTrue(isinstance(tuple(p), tuple))

    def testAngle(self):
        p = self.p.copy()
        self.assertEqual(p.angle, 0)
        p.center = 1,0
        self.assertEqual(p.angle, 0)
        p.center = 0, 10
        self.assertEqual(p.angle, 90)

    def testOrientation(self):
        p = self.p.copy()
        self.assertEqual(p.orientation, 0)
        l = list(p)
        p.orientation = 90
        self.assertNotEqual(p, l)
        self.assertAlmostEqual(p[0].x, -1, 0.001)
        self.assertAlmostEqual(p[0].y, -1, 0.001)
        self.assertAlmostEqual(p[1].x, 1, 0.001)
        self.assertAlmostEqual(p[1].y, -1, 0.001)
        self.assertAlmostEqual(p[2].x, 1, 0.001)
        self.assertAlmostEqual(p[2].y, 1, 0.001)
        self.assertAlmostEqual(p[3].x, -1, 0.001)
        self.assertAlmostEqual(p[3].y, 1, 0.001)

    def testCollision(self):
        p1 = self.p.copy()
        p2 = [(-0.5,0.5), (-0.5,-0.5), (0.5,-0.5), (0.5,0.5)]
        self.assertTrue(p1.intersects(p2))
        self.assertTrue(p1.intersects(p1))
        p1.center = 90, -60
        self.assertFalse(p1.intersects(p2))
        p1.center = 1.5, 0
        self.assertTrue(p1.intersects(p2))
        p1.center = 0, -1.5
        self.assertTrue(p1.intersects(p2))
        p1.center = -1.4, 0
        self.assertTrue(p1.intersects(p2))

    def testPickle(self):
        testpoly = flamingo.flmath.Polygon([(-1,1), (-1,-1), (1,-1), (1,1)])
        testpoly_str = pickle.dumps(testpoly)
        loaded_poly = pickle.loads(testpoly_str)
        self.assertEqual(testpoly, loaded_poly)

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.Polygon, b)


class TestRect(unittest.TestCase):
    def setUp(self):
        self.p = flamingo.flmath.Rect((0, 0), 2, 2)

        self.bad = [[1, 2, 3],
                    [{'foo': 'bar'}, "meow!", (1, 2), ["3","4"]],
                    [(1,), (2,), (3,)]]

    def testAccess(self):
        p = self.p.copy()
        self.assertEqual(p.center, (0,0))
        self.assertEqual(p.topleft, (-1, 1))
        self.assertEqual(p.bottomleft, (-1, -1))
        p.center = 1, 3
        self.assertEqual(p.center, (1, 3))
        p.topright = 4
        self.assertEqual(p.topright, (4, 4))
        self.assertEqual(p.bottomright, (4, 2))
        p[1] = 4, 1
        self.assertEqual(p.topright, (4, 3))
        self.assertEqual(p.bottomright, (4, 1))
        p.width = 4
        self.assertEqual(p.topright, (5, 3))
        p.size = (1, 1)
        self.assertEqual(p.topleft, (2.5, 2.5))

    def testComparison(self):
        p = self.p.copy()
        q = [(-1, -1), (1, -1), (1, 1), (-1, 1)]
        self.assertEqual(p, q)
        q[3] = (-1, 2)
        self.assertNotEqual(p, q)

    def testAppend(self):
        p = self.p.copy()
        self.assertRaises(TypeError, flamingo.flmath.Rect.append, p, (0,0))

    def testInsert(self):
        p = self.p.copy()
        self.assertRaises(TypeError, flamingo.flmath.Rect.insert, p, 1, (0,0))

    def testRemove(self):
        p = self.p.copy()
        self.assertRaises(TypeError, flamingo.flmath.Rect.remove, p, 1)

    def testAngle(self):
        p = self.p.copy()
        self.assertEqual(p.angle, 0)
        p.center = 1,0
        self.assertEqual(p.angle, 0)
        p.center = 0, 10
        self.assertEqual(p.angle, 90)
        p.angle = 0
        self.assertEqual(p.center, (10, 0))

    def testOrientation(self):
        p = self.p.copy()
        self.assertEqual(p.orientation, 0)
        l = list(p)
        p.orientation = 90
        self.assertNotEqual(p, l)
        self.assertAlmostEqual(p[0].x, 1, 0.001)
        self.assertAlmostEqual(p[0].y, -1, 0.001)
        self.assertAlmostEqual(p[1].x, 1, 0.001)
        self.assertAlmostEqual(p[1].y, 1, 0.001)
        self.assertAlmostEqual(p[2].x, -1, 0.001)
        self.assertAlmostEqual(p[2].y, 1, 0.001)
        self.assertAlmostEqual(p[3].x, -1, 0.001)
        self.assertAlmostEqual(p[3].y, -1, 0.001)

    def testConversion(self):
        p = self.p.copy()
        self.assertEqual(list(p), p)
        self.assertTrue(isinstance(list(p), list))
        self.assertEqual(tuple(p), p)
        self.assertTrue(isinstance(tuple(p), tuple))

    def testPickle(self):
        testrect = flamingo.flmath.Rect((-1, 1), 2, 2)
        testrect_str = pickle.dumps(testrect)
        loaded_rect = pickle.loads(testrect_str)
        self.assertEqual(testrect, loaded_rect)

    def testBad(self):
        for b in self.bad:
            self.assertRaises(TypeError, flamingo.flmath.Rect, b)


##-------- Test Suite
testpow             = unittest.TestLoader().loadTestsFromTestCase(TestPow)
testdistance        = unittest.TestLoader().loadTestsFromTestCase(TestDistance)
testmidpoint        = unittest.TestLoader().loadTestsFromTestCase(TestMidpoint)
testarea            = unittest.TestLoader().loadTestsFromTestCase(TestArea)
testnormalized      = unittest.TestLoader().loadTestsFromTestCase(TestNormalizeAngle)
testnormalizepoly   = unittest.TestLoader().loadTestsFromTestCase(TestNormalizePoly)
testsimplify        = unittest.TestLoader().loadTestsFromTestCase(TestPolySimplify)
testvector          = unittest.TestLoader().loadTestsFromTestCase(TestVector)
testpolygon         = unittest.TestLoader().loadTestsFromTestCase(TestPolygon)
testrect            = unittest.TestLoader().loadTestsFromTestCase(TestRect)

testsuite = unittest.TestSuite((testpow, testdistance, testmidpoint, testarea,
                                testnormalized, testnormalizepoly, #testsimplify,
                                testvector, testpolygon, testrect))

if __name__ == "__main__":
    unittest.TextTestRunner(verbosity=2).run(testsuite)
